package sync

import (
	"time"

	"gitee.com/yrwy/msgo/pkg/errors"
)

//数据同步
type SyncValue[T any] chan T

func NewSyncValue[T any]() SyncValue[T] {
	return SyncValue[T](make(chan T))
}

func (s SyncValue[T]) Close() (e error) {
	defer func() {
		if p := recover(); p != nil {
			e = errors.ErrClosed
		}
	}()
	close(s)
	return
}

func (s SyncValue[T]) Recv() <-chan T {
	return s
}

func (s SyncValue[T]) Send() chan<- T {
	return s
}

func (s SyncValue[T]) WaitSend(v T) {
	s <- v
}

func (s SyncValue[T]) WaitRecv() T {
	return <-s
}

func (s SyncValue[T]) TrySend(v T) bool {
	select {
	case s <- v:
		return true
	default:
	}
	return false
}

func (s SyncValue[T]) TryRecv() (T, bool) {
	select {
	case v := <-s:
		return v, true
	default:
	}
	return *new(T), false
}

func (s SyncValue[T]) TimedSend(v T, dur time.Duration) bool {
	timer := time.NewTimer(dur)
	defer timer.Stop()
	select {
	case s <- v:
		return true
	case <-timer.C:
	}
	return false
}

func (s SyncValue[T]) TimedRecv(dur time.Duration) (T, bool) {
	timer := time.NewTimer(dur)
	defer timer.Stop()
	select {
	case v := <-s:
		return v, true
	case <-timer.C:
	}
	return *new(T), false
}
